package jmine.tec.script;

import jmine.tec.annotations.Unmodifiable;
import jmine.tec.script.impl.beanshell.BeanshellScriptExecutor;

/**
 * Executor de beanshell que caso consiga compilar o script irá executá-lo de forma compilada, caso contrário utiliza o modo interpretado.
 * 
 * @author lundberg
 */
@Unmodifiable
public class LenientCompiledBeanshellExecutor implements ScriptExecutor, WrappingScriptExecutor {

    private CompiledBeanshellExecutor compiledExecutor;

    private BeanshellScriptExecutor interpretedExecutor;

    /**
     * {@inheritDoc}
     */
    public <R> R execute(ScriptExecutionContext<R> context) throws ScriptExecutorException {
        return this.findDelegateFor(context).execute(context);
    }

    /**
     * {@inheritDoc}
     */
    public <R> R getDependencies(ScriptExecutionContext<R> context) throws ScriptExecutorException {
        return this.findDelegateFor(context).getDependencies(context);
    }

    /**
     * {@inheritDoc}
     */
    public <R> R getValidations(ScriptExecutionContext<R> context) throws ScriptExecutorException {
        return this.findDelegateFor(context).getValidations(context);
    }

    /**
     * Busca o executor mais adequado ao contexto
     * 
     * @param context context
     * @return ScriptExecutor
     */
    protected ScriptExecutor findDelegateFor(ScriptExecutionContext<?> context) {
        if (this.compiledExecutor.canExecute(context)) {
            return this.compiledExecutor;
        } else {
            return this.interpretedExecutor;
        }
    }

    /**
     * @param compiledExecutor the compiledExecutor to set
     */
    public void setCompiledExecutor(CompiledBeanshellExecutor compiledExecutor) {
        this.compiledExecutor = compiledExecutor;
    }

    /**
     * @param interpretedExecutor the interpretedExecutor to set
     */
    public void setInterpretedExecutor(BeanshellScriptExecutor interpretedExecutor) {
        this.interpretedExecutor = interpretedExecutor;
    }

    /**
     * {@inheritDoc}
     */
    public Class<? extends ScriptExecutor> getWrappedExecutorType() {
        return BeanshellScriptExecutor.class;
    }
}
